package zookeeper.test1;

import org.apache.zookeeper.*;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;

public class ZkLock {
    private ZooKeeper zooKeeper;

    private static CountDownLatch latch=new CountDownLatch(1);
    public ZkLock(ZooKeeper zooKeeper) {
        //如果有多个的话 逗号分隔 new ZooKeeper("127.0.0.1:2181，127.0.0.1:2181")
        try {
            this.zooKeeper = new ZooKeeper("127.0.0.1:2181",5000,new IWatcher());
            latch.await();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    public static ZkLock getInstance(){
        return Singleton.getInstance();
    }

    /**
     * 如果创建成功，表示获取锁成功，创建失败，抛出异常，要重试获取锁。
     * @param id
     */
    private void lock(int id){
        String path="/test/product/"+id;
        //param1:路径，param2: 数据，这里不需要数据，所以是“”，param3:acl，param4,模式，临时节点
        //还是永久节点，创建锁的时候必须是临时节点。
        try {
            zooKeeper.create("path","".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        } catch (KeeperException e) {
            //当节点已经存在，或者其他原因时会存在异常， 要重试获取锁
            while(true){
                try{
                    Thread.sleep(500);
                }catch (Exception e1){
                    e1.printStackTrace();
                }
                try {
                    zooKeeper.create("path","".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
                }catch (Exception e2){
                    continue;
                }
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 释放锁
     * @param id
     */
    private void unlock(int id){
        String path="/test/product/"+id;
        try {
            //第二个参数表示版本，-1表示不限制版本
            zooKeeper.delete(path,-1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //自定义watch 实现 zk提供的watch,这个方法是监听连接状态的，连接到达哪一步的时候会触发这个watch
    private class IWatcher implements Watcher{

        @Override
        public void process(WatchedEvent event) {
            System.out.println("zookeeper 连接状态----"+event);
            //说明当前连上了
            if(Event.KeeperState.SyncConnected==event.getState()){
                latch.countDown();
            }
        }
    }

     private static class Singleton{
        private static  ZkLock instance;

        static {
           // instance=new ZkLock();
            instance=null;
        }
        private static ZkLock getInstance(){
            return instance;
        }
    }
}
